package src;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

public class Numbers {

  /****************************************************************
  * Function: allCombinations
  * Inputs: @param n;
  *     The size of the given set
  * Inputs: @param c;
  *     The size of each subset
  * Output: void
  *
  * Description: Given a set of numbers ranging from 0 to n-1, print
  *    all combinations of size c. For example, if a set has 5
  *    elements as [0,1,2,3,4] then there are 10 combinations of
  *    size 3 because 5C3 = 5!/(3!(5-3)!) = 10. And the combinations
  *    are: [0, 1, 2]; [0, 1, 3]; [0, 1, 4]; [0, 2, 3]; [0, 2, 4];
  *    [0, 3, 4]; [1, 2, 3]; [1, 2, 4]; [1, 3, 4]; [2, 3, 4].
  *    Notice that each subset is distinct from every other subset.
  *
  * Technical Details: 
  *   0] create an int array of size c and fill it with the numbers
  *     0,1,3, ..., c-1.
  *   1] calculate the total number of combinations expected:
  *    total = n!/(c!(n-c)!)
  *   2] print the array, as the first combination
  *   3] for total-1 times, call the function nextCombination on
  *     the array and then print the array.
  *   Note: each call to nextCombination recombines the array.
  * 
  *   While this algorithm is straightforward (from the
  *   ensuing code), applying it can be a bit tricky. The idea is to
  *   use the resulting combinations as the indexes of some other
  *   collection. See the function zeroSumTripplets in this class
  *   for a good example.
  *
  *****************************************************************/
  public void allCombinations(int n, int c) {
    int[] indexes = new int[c];
    // fill the array with numbers from 0 to n-1
    for (int i = 0; i < c; i++)
      indexes[i] = i;
    int total = combinationSize(n, c);
    // run through and print all the combinations
    for (int i = 0; i < total; i++) {
      if (0 != i)
        nextCombination(indexes, n, c);
      System.out.println(Arrays.toString(indexes));
    }
  }// allCombinations(int,int)
   
  private int combinationSize(int n, int c) {
    // shortcut for calculating n!/(c!(n-c)!)
    if (c > n)
      return -1;
    int sp = n - c < c ? c : n - c;// sp = startingPoint
    double res = sp + 1;
    int i = (int) res + 1;
    while (i <= n) {
      res *= (double) i / (i - sp);
      i++;
    }
    return (int) res;
  }// combinationSize(int, int)
   
  private void nextCombination(int[] A, int n, int c) {
    int i = c - 1;
    while (n - c + i == A[i])
      i--;
    A[i]++;
    for (int j = i + 1; j < c; j++)
      A[j] = A[i] + j - i;
  }// nextCombination(int[], int, int)

  // /-------------+------+-------------+------+-------------+------

  /*****************************************************************
   * Function: allPrimes
   * Inputs: @param max
   *      The highest number to return
   * Output: List<Integer>
   *      list of all the prime numbers.
   *
   * Description: This function returns a list of all the prime
   *    numbers between 2 and max, inclusive.
   *
   * Technical Details: Arithmetic review:
   *   0) 0 and 1 are not prime numbers.
   *   1) The first prime number is 2.
   *   2) A number is prime if it is only divisible by itself and by 1
   *   3) If y is the square root of x (i.e. y = x^0.5); then if x is
   *    not divible by any number between 2 and y, inclusive;
   *    then x is prime.
   *
   *****************************************************************/
  public List<Integer> allPrimes(int max) {
    if (2 > max)
      return null;
    boolean[] primes = new boolean[max + 1];
    Arrays.fill(primes, true);
    primes[0] = primes[1] = false;
    for (int i = 2, sqrt = (int) Math.sqrt(max); i <= sqrt; i++)
      if (primes[i])
        for (int k = 2; k * i <= max; k++)
          if (primes[k * i])
            primes[k * i] = false;
    List<Integer> result = new ArrayList<Integer>();
    for (int i = 2; i <= max; i++)
      if (primes[i])
        result.add(i);
    return result;
  }// allPrimes()

  ///-------------+------+-------------+------+-------------+------

  /******************************************************************
   * Function: baseToBaseConversion
   * Inputs: @param num
   *     The number to convert
   * Inputs: @param b1
   *     The base to convert from
   * Inputs: @param b2
   *     The base to convert to
   * Output: String
   *     The converted number.
   *
   * Description: This function converts a number from virtually
   *   any given base b1 to any specified base b2.
   *
   * Technical Details: The CIPHERS strings in the function determine
   *   the bases of operation: if the ciphers were "0123456789ABCDEF"
   *   the function would be limited to bases up to hexadecimal.
   *
   *   Converting into and out of the decimal system tends to be
   *   intuitive. Hence, the algorithm transacts in decimal.
   *   Note that the toDecimal and fromDecimal codes are useful
   *   functions in their own right (so they are declared public).
   *
   *****************************************************************/
  public String baseToBaseConversion(String num, int b1, int b2) {
    return fromDecimal(toDecimal(num, b1), b2);
  }// baseToBaseConversion(long,int,int)

  public int toDecimal(String num, int b) {
    final String CIPHERS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int result = 0;
    int mult = 1;

    for (int i = num.length() - 1; i >= 0; i--) {
      result += CIPHERS.indexOf(num.charAt(i)) * mult;
      mult *= b;
    }// for
    return result;
  }// toDecimal(String,int)
   
  public String fromDecimal(int num, int b) {
    final String CIPHERS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    String result = "";

    while (0 < num) {
      result = CIPHERS.charAt((num % b)) + result;
      num /= b;
    }// while
    return result;
  }// fromDecimal(long,int)

  // /-------------+------+-------------+------+-------------+------

  /******************************************************************
   * Function: baseToBaseConversion
   * Inputs: @param num
   *     The number to convert
   * Inputs: @param b1
   *     The base to convert from
   * Inputs: @param b2
   *     The base to convert to
   * Output: long
   *
   * Description: This function transacts in bases less than or equal
   *   to ten (10). It is structurally similar to the overloaded more
   *   general version above.
   *
   * Technical Details: The fromDecimal and toDecimal functions are
   *   structurally and logically similar. Interchanging the bases
   *   b and 10 in one function will result in the other. Compiling
   *   a few examples by hand will readily show why.
   *
   *****************************************************************/
  public long baseToBaseConversion(long num, int b1, int b2) {
    return fromDecimal(toDecimal(num, b1), b2);
  }// baseToBaseConversion(long,int,int)

  public long fromDecimal(long num, int b) {
    int result = 0;
    int mult = 1;
    while (0 < num) {
      result += (num % b) * mult;
      mult *= 10;
      num /= b;
    }// while
    return result;
  }// fromDecimal(long,int)

  public long toDecimal(long num, int b) {
    int result = 0;
    int mult = 1;
    while (0 < num) {
      result += (num % 10) * mult;
      mult *= b;
      num /= 10;
    }// while
    return result;
  }// toDecimal(String,int)
   ///-------------+------+-------------+------+-------------+------

   public int division(int divident, int divisor) {
    int result = 0, track = 0;
    for (int i = 1; i <= divident; i++) {
      track++;
      if (track == divisor) {
        result++;
        track = 0;
      }
    }
    return result;
  }//division(int,int)

  // /-------------+------+-------------+------+-------------+------
   
   /****************************************************************
    * Function: fractionAddition
    * Inputs: @param a
    *     2-element array representing first fraction as 
    *     {numerator, denominator}
    * Inputs: @param b
    *     2-element array representing second fraction as 
    *     {numerator, denominator}
    * Output: int[]
    *     reduced form result of a+b as {numerator, denominator}
    *
    * Description: Given two fractions a and b return the sum in
    *    reduced form. The arrays are given and returned as
    *    {numerator, denominator}
    *
    * Technical Details: This is a brute force algorithm.
    *
    ***************************************************************/
  public int[] fractionAddition(int[] a, int[] b) {
    int denominator = LCM(a[1], b[1]);
    int numA = denominator / a[1] * a[0];
    int numB = denominator / b[1] * b[0];
    int numerator = numA + numB;
    int gcd = GCD(numerator, denominator);
    return new int[] { numerator / gcd, denominator / gcd };
  }// fractionAddition(int[],int[])

  // /-------------+------+-------------+------+-------------+------

  /******************************************************************
   * Function: fractionDivision
   * Inputs: @param a
   *     2-element array representing first fraction as 
   *     {numerator, denominator}
   * Inputs: @param b
   *     2-element array representing second fraction as 
   *     {numerator, denominator}
   * Output: int[]
   *     reduced form result of a*b as {numerator, denominator}
   *
   * Description: Given two fractions a and b return the quotient in
   *    reduced form. The arrays are given and returned as
   *    {numerator, denominator}
   *
   * Technical Details: This is a brute force algorithm.
   *
   *****************************************************************/
  public int[] fractionDivision(int[] a, int[] b) {
    int numerator = a[0] * b[1];
    int denominator = a[1] * b[0];
    int gcd = GCD(numerator, denominator);
    gcd = 0 > gcd ? -gcd : gcd;
    return new int[] { numerator / gcd, denominator / gcd };
  }// fractionDivision(int[],int[])

  // /-------------+------+-------------+------+-------------+------

  /******************************************************************
   * Function: fractionMultiplication
   * Inputs: @param a
   *     2-element array representing first fraction as 
   *     {numerator, denominator}
   * Inputs: @param b
   *     2-element array representing second fraction as 
   *     {numerator, denominator}
   * Output: int[]
   *     reduced form result of a*b as {numerator, denominator}
   *
   * Description: Given two fractions a and b return the product in
   *    reduced form. The arrays are given and returned as
   *    {numerator, denominator}
   *
   * Technical Details: This is a brute force algorithm.   
   *
   *****************************************************************/
  public int[] fractionMultiplication(int[] a, int[] b) {
    int numerator = a[0] * b[0];
    int denominator = a[1] * b[1];
    int gcd = GCD(numerator, denominator);
    gcd = 0 > gcd ? -gcd : gcd;
    return new int[] { numerator / gcd, denominator / gcd };
  }// fractionMultiplication(int[],int[])

  // /-------------+------+-------------+------+-------------+------

  /******************************************************************
   * Function: fractionSubtraction
   * Inputs: @param a
   *     2-element array representing first fraction as 
   *     {numerator, denominator}
   * Inputs: @param b
   *     2-element array representing second fraction as 
   *     {numerator, denominator}
   * Output: int[]
   *     reduced form result of a-b as {numerator, denominator}
   *
   * Description: Given two fractions a and b return the difference
   *    in reduced form. The arrays are given and returned as
   *    {numerator, denominator}
   *
   * Technical Details: This is a brute force algorithm.
   *
   *****************************************************************/
  public int[] fractionSubtraction(int[] a, int[] b) {
    int denominator = LCM(a[1], b[1]);
    int numA = denominator / a[1] * a[0];
    int numB = denominator / b[1] * b[0];
    int numerator = numA - numB;
    int gcd = GCD(numerator, denominator);
    gcd = 0 > gcd ? -gcd : gcd;
    return new int[] { numerator / gcd, denominator / gcd };
  }// fractionAddition(int[],int[])

  // /-------------+------+-------------+------+-------------+------
  /******************************************************************
   * Function: fibonacci
   * Inputs: @param k
   * Output: int
   *
   * Description: This function returns the kth fibonacci number.
   *
   * Technical Details: Recall that the fibonacci sequence is:
   *   0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, .... The sequence is
   *   formed by adding the preceeding two numbers. The base/anchor
   *   case for the sequence is 0th = 0 and 1st = 1.
   *
   * Alternate Algorithm: The presented recursive definition is a bit
   *    expensive as it uses an implicit stack. The alternate
   *    iterative version below uses no stack.
   *
   *   public int fibonacci(int k) {
   *     if(2 > k) return k;
   *     int a = 0, b = 1, t;
   *     for(int i=2; i <= k; i++) {
   *       t = a+b;
   *       a = b;
   *       b = t;
   *     }
   *     return b;
   *  }
   *
   *****************************************************************/
  public int fibonacci(int k) {
    if (2 > k)
      return k;
    return fibonacci(k - 1) + fibonacci(k - 2);
  }// fibonacci(int)
  // /-------------+------+-------------+------+-------------+------
  
  /******************************************************************
   * Function: GCD
   * Inputs: @param a
   *     One of the numbers to use to compute GCD
   * Inputs: @param b
   *     One of the numbers to use to compute GCD
   * Output: long
   *    The GCD computed.
   *
   * Description: This function finds the greatest common
   *    divisor/denominator of the given numbers. The GCD of x and y
   *    is the greatest integer that divides both x and y evenly.
   *    For example the gcd of 18 and 27 is 9 because 9*3 = 27 and
   *    9*2= 18.
   *
   * Technical Details: Mathematicians have found numerous techniques
   *    for calculating the GCD of two numbers. The present
   *    implementation uses the mod operator. Other implementations
   *    may use subtraction, for example.
   *
   *****************************************************************/
  public int GCD(int a, int b) {
    if (0 == a || 0 == b)
      return -1;
    if (1 == a || 1 == b)
      return 1;

    while (0 < a && 0 < b) {
      if (a > b)
        a %= b;
      else
        b %= a;
    }// while
    return 0 == a ? b : a;
  }// GCD(int,int)
  // /-------------+------+-------------+------+-------------+------

  /******************************************************************
   * Function: isPrime
   * Inputs: @param num
   *      The number to check
   * Output: boolean
   *     
   * Description: This function indicates whether the given number is
   *    prime.
   *
   * Technical Details:  Arithmetic review:
   *   0) 0 and 1 are not prime numbers.
   *   1) The first prime number is 2.
   *   2) A number is prime if it is only divisible by itself and by 1
   *   3) If y is the square root of x (i.e. y = x^0.5); then if x is
   *    not divible by any number between 2 and y, inclusive;
   *    then x is prime.
   * 
   * Alternate Algorithm:
   *   if(2 > num) return false;
   *   if(2 == num) return true;
   *   if(0 == num %2) return false;
   *   for(long i=3, sqt = (long) Math.sqrt(num); i <= sqt; i++ )
   *     if(0 ==  num % i) 
   *       return false;
   *   return true;
   *
   *****************************************************************/
  public boolean isPrime(int num) {
    if (2 > num)
      return false;
    boolean[] primes = new boolean[num + 1];
    Arrays.fill(primes, true);
    primes[0] = primes[1] = false;
    int sqrt = (int) Math.sqrt(num);
    for (int i = 2; i <= sqrt && primes[num]; i++)
      if (primes[i])
        for (int k = 2; k * i <= num; k++)
          if (primes[k * i])
            primes[k * i] = false;
    return primes[num];
  }// isPrime(long)
  // /-------------+------+-------------+------+-------------+------

  /*****************************************************************
   * Function: LCM
   * Inputs: @param a
   *     One of the numbers to use to compute LCM
   * Inputs: @param b
   *     One of the numbers to use to compute LCM
   * Output: int
   *     The LCM of a and b
   *
   * Description: This function computes the lowest common multiplier
   *   of two given numbers. The lcm of two numbers a and b is the
   *   smallest number that can be divided by both a and b. For 
   *   example, 15 is the lcm of 3 and 5 because 15 is the lowest
   *   number that can be evenly devided by both 3 and 5; 18 is the
   *   lcm of 6 and 9 because 18 is the lowest number that can be
   *   divided by both 6 and 9.
   *
   * Technical Details: Mumerous techniques have been developed to
   *   compute the lcm of two numbers. The present algorithm uses
   *   (a*b)/gcd(a,b) = lcm (a,b).
   *
   *****************************************************************/
  public int LCM(int a, int b) {
    if (a > b)
      return (a / GCD(a, b) * b);
    else
      return (b / GCD(a, b) * a);
  }// LCM(int,int)
  // /-------------+------+-------------+------+-------------+------

  /******************************************************************
   * Function: nQueenSolution
   * Inputs: @param n
   * Output: int[]
   *
   * Description: This function solves the following classical
   *    problem: Given an n by n chessboard, place n queens on the
   *    board such that no queen is threatened.
   *
   * Technical Details: Since there can only be one queen per row, a
   *   one dimensional array is used to represent the board. The
   *   values inside the array represent the columns of the
   *   chessboard. As such, each element of the array can take a
   *   value between 0 and n-1.
   *
   *   The presented algorithm is based on the following personal
   *   observation. A queen on cell (x,y) dominates all cells in
   *   row x, in column y, or in any cell (j,k) where (j-k)==(x-y) or
   *   (j+k)==(x+y).
   * 
   *   Beginning with the first row (i.e. x=0), the addQueen function
   *   is called recursively so as to dynamically adjust the board
   *   until all n queens are placed safely.
   *
   *****************************************************************/
  public int[] nQueenSolution(int n) {
    int[] queens = new int[n];
    addQueen(0, queens, n);
    return queens;
  }// nQueens(int)

  private void addQueen(int x, int[] queens, final int n) {
    for (int i = 0; i < n && 0 == queens[n - 1]; i++)
      if (safeToAdd(x, i, queens)) {
        queens[x] = i;
        addQueen(x + 1, queens, n);
      }
  }// addQueen(int, int[], final int)

  private boolean safeToAdd(int x, int y, int[] queens) {
    for (int i = 0; i < x; i++)
      if (y == queens[i] || (x - y) == (i - queens[i])
          || (x + y) == (i + queens[i]))
        return false;
    return true;
  }// safeToAdd(int, int, int[])
  // /-------------+------+-------------+------+-------------+------

  /******************************************************************
   * Function: permutation
   * Inputs: @param list
   *      the list whose permutations to find
   * Output: List<Integer[]>
   *      the list of permutations
   *
   * Description: This function returns a lists of all the
   *    permutations of a given set. For example, given the set
   *    {1,2,3}, the permutations are: {1,2,3}; {1,3,2};
   *    {2,1,3}; {2,3,1}; {3,1,2}; {3,2,1}. From arithmetics, we know
   *    that the number of permutations for a set is equal to the
   *    factorial of the size of the set: 3! = 6.
   *
   * Technical Details: This algorithm is usually referred to as
   *    Heap's permutation, in honor of B. R. Heap.
   * 
   *    The present implementation of the algorithm uses two
   *    overloaded instances of the permutation method. In the first
   *    instance, the method takes an integer array and returns a
   *    list of integer arrays, List<Integer[]> permutation
   *    ( Integer[] ). In the second instance the method takes
   *    multiple inputs and returns nothing, void permutation
   *    (Integer[], int, List<Integer[]>). Notice also that the second
   *    version of the method is recursive.
   * 
   *    If a programmer simply wishes to print the permutations
   *    instead of returning them in a list, [code 2] should replace
   *    [code 1] below.
   * 
   *   [code 1]:
   *     if(1 == n)
   *       factorials.add(Arrays.copyOf(list, list.length));
   *     
   *   [code 2]:
   *    if(1 == n){
   *     for(int i: list)
   *      System.out.print(i+", ");
   *     System.out.println();
   *    }  
   *
   *****************************************************************/
  public List<Integer[]> permutation(Integer[] list) {
    List<Integer[]> factorials = new ArrayList<Integer[]>();
    permutation(list, list.length, factorials);
    return factorials;
  }// permutation(Integer[])
   
  private
  void permutation(Integer[] list, int n, List<Integer[]> factorials){
    if (1 == n)
      factorials.add(Arrays.copyOf(list, list.length));
    else {
      for (int i = 0; i < n; i++) {
        permutation(list, n - 1, factorials);
        if (0 == n % 2)
          swap(list, 0, n - 1);
        else
          swap(list, i, n - 1);
      }// for
    }// if
  }// permutation(Integer[], int, List<Integer[]>)

  private void swap(Integer[] list, int x, int y) {
    Integer t = list[x];
    list[x] = list[y];
    list[y] = t;
  }// swap(Integer[], int, int)
  ///-------------+------+-------------+------+-------------+------

  /******************************************************************
   * Function: pow
   * Inputs: @param base
   * Inputs: @param exponent
   * Output: int
   *
   * Description: Return the value of the given base raised to the
   *    power of the given exponent.
   * 
   * Restrictions: Both numbers must be positive for this algorithm to
   *    work. A more general solution that includes negative values 
   *    would obscure the algorithm against neophyte developers.
   * 
   * Technical Details: This is a very simple problem that could be
   *    solved with the Alternate Algorithm below. However, when
   *    speed of execution becomes important, it becomes unclear
   *    whether the Presented Algorithm or the Alternate Algorithm
   *    is faster.
   * 
   *    At the hardware level multiplication is much more time
   *    consuming than addition (for lessons on digital logics
   *    see www.teahlab.com). Hence, while on the surface the time
   *    complexity of the Alternate Algorithm O(exponent) appears much
   *    smaller than the time complexity of the Presented Algorithm
   *    O(exponent * base); the Presented Algorithm is a safer bet
   *    simply because the programmer takes matter into his own hands
   *    as opposed to relying on how a computer's ALU is designed.
   *
   * Alternate Algorithm:
   *  public int pow(int base, int exponent) {
   *     if(0 == exponent)
   *    return 1;
   *     int result = base;
   *     for(int e = 1; e < exponent; e++)
   *    result*=base;
   *     return result;
   *  }//pow
   *****************************************************************/
  public int pow(int base, int exponent) {
    if (0 == exponent)
      return 1;
    int result = base, product;
    for (int e = 1; e < exponent; e++) {
      product = result;
      for (int b = 1; b < base; b++)
        result += product;
    }
    return result;
  }// pow
  // /-------------+------+-------------+------+-------------+------

  /******************************************************************
   * Function: shuffle
   * Inputs: @param arr
   *      The array to shuffle
   * Output: void
   *
   * Description: Randomly shuffle the elements of the given array.
   *    This Algorithm may be applied to shuffle a deck of cards;
   *    in which case each card would be an element of the array.
   *
   * Technical Details: The for-loop starts at i=arr.length instead of
   *   i=0 because Java's built-in random number generator nextInt(i)
   *   will generate a number between 0 and i-1, inclusive.
   *   Furthermore, i > 0 is used because nextInt(0) would generate
   *   an exception. 
   *
   *****************************************************************/
  public void shuffle(Object[] arr) {
    Random rand = new Random();
    for (int i = arr.length; i > 0; i--)
      swap(arr, i - 1, rand.nextInt(i));
  }// shuffle(Object[])
   
  private void swap(Object[] arr, int a, int b) {
    Object tmp = arr[a];
    arr[a] = arr[b];
    arr[b] = tmp;
  }// swap(Object[], int, int)
  // /-------------+------+-------------+------+-------------+------

  /******************************************************************
   * Function: zeroSumTripplet
   * Inputs: @param A
   *     The given array
   * Inputs: @param tuple
   *     The number of elements to choose
   * Inputs: @param sum
   *     The target sum the choosen elements must add to.
   * Output: void
   *
   * Description: The name of this function comes from the particular
   *    problem which this general solution answers. The particular
   *    problem was posed as follows: Given an integer array A, find
   *    all triplets that sum up to zero(0).
   *
   *   This solution addresses the broader problem: given a set of
   *   size n (i.e. A.length) choose all distinct subsets of size c
   *   (i.e. tuple), such that the elements of the subset must add
   *   up to a target sum.
   *
   * Technical Details:
   *   1] Calculate the total number of combinations expected:
   *     total = n!/(c! *(n-c)!)
   *   2] Create an index array and fill it with the first c-1 indexes
   *     starting from 0.
   *   3] For i from 0 to total -1
   *     1) if i is not zero, THEN get the next distinct combination
   *     2) check for and print matches
   * 
   * NOTE: The function to find the next combination is simple:
   * 
   *   nextCombination(int[] X, int n, int c){
   *    int i = c-1;
   *    while(X[i] == n-c+i)
   *      i--;
   *    X[i]++;
   *    for(int j=i+1; j<c; j++)
   *      X[j] =  X[i]+j-i;    
   *   }
   *
   *****************************************************************/
  public void zeroSumTripplets(int[] A, int tuple, int sum) {
    int[] index = new int[tuple];
    for (int i = 0; i < tuple; i++)
      index[i] = i;
    int total = combinationSize(A.length, tuple);
    for (int i = 0; i < total; i++) {
      if (0 != i)
        nextCombination(index, A.length, tuple);
      printMatch(A, Arrays.copyOf(index, tuple), sum);
    }// for
  }// zeroSumTripplets(int[], int, int)

  private void printMatch(int[] A, int[] ndx, int sum) {
    int calc = 0;
    for (int i = 0; i < ndx.length; i++)
      calc += A[ndx[i]];
    if (calc == sum) {
      Integer[] t = new Integer[ndx.length];
      for (int i = 0; i < ndx.length; i++)
        t[i] = A[ndx[i]];
      System.out.println(Arrays.toString(t));
    }// if
  }// printMatch(int[], int[], int)
   ///-------------+------+-------------+------+-------------+------
}//class: Numbers